package top.zlhy7.module.work.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import top.zlhy7.base.request.PageQueryVo;
import top.zlhy7.enums.OrderTypeEnum;
import top.zlhy7.exception.ServiceException;
import top.zlhy7.module.dept.entity.SysDept;
import top.zlhy7.module.dept.service.ISysDeptService;
import top.zlhy7.module.work.entity.WordOrder;
import top.zlhy7.module.work.mapper.WordOrderMapper;
import top.zlhy7.module.work.service.IWordOrderService;
import top.zlhy7.module.work.vo.WordOrderVo;
import top.zlhy7.module.work.vo.WorkOrderFenpaiVo;
import top.zlhy7.module.work.vo.WorkOrderStatistics1Vo;
import top.zlhy7.module.work.vo.WorkOrderStatistics2Vo;
import top.zlhy7.module.work.vo.WorkOrderStatistics3Vo;
import top.zlhy7.utils.DateUtils;
import top.zlhy7.utils.MapstructUtils;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author renyong
 * @date 2024/9/29 19:35
 * @description 工单实现类 服务
 */
@RequiredArgsConstructor
@Slf4j
@Service("wordOrderService")
public class WordOrderServiceImpl extends ServiceImpl<WordOrderMapper, WordOrder> implements IWordOrderService {
    /**
     * 部门
     */
    private final ISysDeptService sysDeptService;
    /**
     * 分页查询
     * @param pageQueryVo 查询条件
     * @return
     * @author renyong on 2024/9/29 19:55
     */
    @Override
    public IPage<WordOrderVo> findPage(PageQueryVo<WordOrderVo> pageQueryVo) {
        WordOrderVo query = pageQueryVo.getQuery();
        LambdaQueryWrapper<WordOrder> queryWrapper = Wrappers.lambdaQuery(WordOrder.class)
                .eq(query.getOrderType() != null,WordOrder::getOrderType, query.getOrderType())
                .eq(query.getHandleDeptId() != null,WordOrder::getHandleDeptId, query.getHandleDeptId())
                .eq(query.getIsOverdue() != null,WordOrder::getIsOverdue, query.getIsOverdue())
                .like(StrUtil.isNotBlank(query.getOrderNo()),WordOrder::getOrderNo, query.getOrderNo())
                .like(StrUtil.isNotBlank(query.getTitle()),WordOrder::getTitle, query.getTitle())
                .like(StrUtil.isNotBlank(query.getContent()),WordOrder::getContent, query.getContent())
                .ge(StrUtil.isNotBlank(query.getCreateStartTime()), WordOrder::getCreateTime, query.getCreateStartTime())
                .le(StrUtil.isNotBlank(query.getCreateEndTime()), WordOrder::getCreateTime, query.getCreateEndTime())
                .orderByDesc(WordOrder::getCreateTime);
        return MapstructUtils.selectVoPage(pageQueryVo.build(WordOrder.class), queryWrapper,baseMapper, WordOrderVo.class);
    }
    /**
     * 入库前参数校验
     * @param wordOrderVo 新增/修改的工单vo
     * @return
     * @author renyong on 2024/9/29 21:57
     */
    public void checkData(WordOrderVo wordOrderVo){
        if (!OrderTypeEnum.orderTypeEnumMap.containsKey(wordOrderVo.getOrderType())) {
            throw new ServiceException().format("工单类型【{}】不存在", wordOrderVo.getOrderType());
        }
        // 工单编号唯一
        LambdaQueryWrapper<WordOrder> queryWrapper = Wrappers.lambdaQuery(WordOrder.class)
                .eq(WordOrder::getOrderNo, wordOrderVo.getOrderNo())
                .ne(wordOrderVo.getId()!=null,WordOrder::getId, wordOrderVo.getId());
        boolean isExist = count(queryWrapper) > 0;
        if (isExist){
            throw new ServiceException().format("工单编号【{}】已存在", wordOrderVo.getOrderNo());
        }
    }
    /**
     * 新增
     * @param wordOrderVo
     * @return
     * @author renyong on 2024/9/29 21:43
     */
    @Override
    public void insert(WordOrderVo wordOrderVo) {
        if(wordOrderVo == null){
            throw new ServiceException("参数错误");
        }
        // 校验数据
        checkData(wordOrderVo);
        WordOrder wordOrder = MapstructUtils.convert(wordOrderVo, WordOrder.class);
        wordOrder.insertBefore();
        save(wordOrder);
    }
    /**
     * 修改
     * @param wordOrderVo
     * @return
     * @author renyong on 2024/9/29 21:43
     */
    @Override
    public void update(WordOrderVo wordOrderVo) {
        if(wordOrderVo == null || wordOrderVo.getId() == null){
            throw new ServiceException("参数错误");
        }
        // 校验数据
        checkData(wordOrderVo);
        WordOrder oldWordOrder = getById(wordOrderVo.getId());
        if (oldWordOrder == null){
            throw new ServiceException("记录不存在");
        }
        WordOrder wordOrder = MapstructUtils.convert(wordOrderVo, WordOrder.class);
        wordOrder.updateBefore();
        updateById(wordOrder);
    }
    /**
     * 删除
     * @param id 主键
     * @return
     * @author renyong on 2024/9/29 21:59
     */
    @Override
    public void delete(Long id) {
        if (id == null){
            throw new ServiceException("主键id不能为空");
        }
        WordOrder wordOrder = getById(id);
        if (wordOrder == null){
            throw new ServiceException("记录不存在");
        }
        removeById(id);
    }
    /**
     * 分派
     * @param workOrderFenpaiVo 分派vo
     * @return
     * @author renyong on 2024/9/29 22:30
     */
    @Override
    public void fenpai(WorkOrderFenpaiVo workOrderFenpaiVo) {
        //region 参数校验
        if (workOrderFenpaiVo==null || workOrderFenpaiVo.getId() == null) {
            throw new ServiceException("参数错误");
        }
        SysDept sysDept = sysDeptService.getById(workOrderFenpaiVo.getHandleDeptId());
        if (sysDept == null){
            throw new ServiceException("部门不存在");
        }
        if (!sysDept.getDeptName().equals(workOrderFenpaiVo.getHandleDeptName())){
            throw new ServiceException("部门名称不正确");
        }
        //endregion
        WordOrder wordOrder = getById(workOrderFenpaiVo.getId());
        // todo 如果要限制存在分派时间，则认为已分派，就不可分派了，这里题目没要求，因此不做限制，可以一直分派
        wordOrder.setHandleDeptId(workOrderFenpaiVo.getHandleDeptId());
        wordOrder.setFenpaiTime(new Date());
        updateById(wordOrder);
    }

    /**
     * 统计1-查询7月每天的工单总量、超期率，超期率=超期工单总量/工单总量
     * @param queryVo 查询条件
     * @return
     */
    @Override
    public List<WorkOrderStatistics1Vo> statistics1(WorkOrderStatistics1Vo queryVo) {
        if (StrUtil.isBlank(queryVo.getYearMonth())) {
            throw new ServiceException("参数错误");
        }
        // 获取某月连续日期
        List<LocalDate> betweenDate = DateUtils.getBetweenDate(LocalDate.parse(queryVo.getYearMonth() + "-01"));
        // 数据库里已有数据的统计结果
        List<WorkOrderStatistics1Vo> workOrderStatistics1List = baseMapper.statistics1(queryVo);
        // 将已有结果列表转为map，key为日期，value为统计结果
        Map<String, WorkOrderStatistics1Vo> workOrderStatistics1Map = workOrderStatistics1List.stream()
                .collect(Collectors.toMap(WorkOrderStatistics1Vo::getStatisticsDate, Function.identity()));
        // 收集统计结果，补齐缺失结果
        List<WorkOrderStatistics1Vo> resultList = new ArrayList<>(betweenDate.size());
        // 遍历日期，如果已有结果里已有数据，则使用已有数据，否则补齐默认数据
        for (LocalDate localDate : betweenDate) {
            resultList.add(workOrderStatistics1Map.getOrDefault(localDate.toString(),
                    new WorkOrderStatistics1Vo(localDate.toString())));
        }
        return resultList;
    }
    /**
     * 工单统计2：查询7月每个部门的工单总量、超期率。
     * @param queryVo 查询条件
     * @return
     */
    @Override
    public List<WorkOrderStatistics2Vo> statistics2(WorkOrderStatistics2Vo queryVo) {
        if (StrUtil.isBlank(queryVo.getYearMonth())) {
            throw new ServiceException("参数错误");
        }
        return baseMapper.statistics2(queryVo);
    }
    /**
     * 工单统计3：查询7月每个工单类型的工单总量、超期率。
     * @param queryVo 查询条件
     * @return
     */
    @Override
    public List<WorkOrderStatistics3Vo> statistics3(WorkOrderStatistics3Vo queryVo) {
        if (StrUtil.isBlank(queryVo.getYearMonth())) {
            throw new ServiceException("参数错误");
        }
        // 查询统计结果
        Map<Integer,WorkOrderStatistics3Vo> workOrderStatistics3VoList = baseMapper.statistics3(queryVo).stream()
                .collect(Collectors.toMap(WorkOrderStatistics3Vo::getOrderType, Function.identity()));
        // 遍历枚举，如果已有结果里已有数据，则使用已有数据，否则补齐默认数据
        List<WorkOrderStatistics3Vo> workOrderStatistics3Vos = Arrays.stream(OrderTypeEnum.values())
                .map(orderTypeEnum -> workOrderStatistics3VoList.getOrDefault(orderTypeEnum.getCode(),
                        new WorkOrderStatistics3Vo(orderTypeEnum.getCode())))
                .collect(Collectors.toList());
        return workOrderStatistics3Vos;
    }
}
